<template>
  <div>
    <router-view v-slot="{ Component }">
      <!-- 不同的name会执行不同的动画效果 -->
      <!-- 当我们进入一个新页面的时候，name变成push  执行新页面跳转动画 -->
      <!-- 当我们返回一个旧页面的时候，name变成back  执行返回动画 -->
      <transition
        @before-enter="beforEnter"
        @after-leave="afterLeave"
        :name="transitionName"
      >
        <!-- 控制缓存组件是一个数组  数组中的原生是组件名称 -->
        <keep-alive :include="VirtualTaskStack">
          <component :is="Component" />
        </keep-alive>
      </transition>
    </router-view>
  </div>
</template>

<script>
// 常量通常是大写，定义一些不变的变量
const ROUTER_TYPE_PUSH = 'push';
const ROUTER_TYPE_BACK = 'back';
const NONE = 'none';
const ROUTER_TYPE_ENUM = [ROUTER_TYPE_PUSH, ROUTER_TYPE_BACK, NONE];
// 因为要做成一个通用的组件，判断当前你的组件使用是否正确
</script>

<script setup>
import { defineProps, ref } from 'vue';
import { useRouter } from 'vue-router';
// 需要做一个标记，标记你是新页面，要执行push动画
// 需要另外的一个标记，表明你是返回旧页面，执行back动画
const props = defineProps({
  // 如果routerType  push   back
  // 路由跳转的类型： push是进入组件   back是退出组件
  //   routerType: {
  //     type: String,
  //     default: NONE,
  //     validator (val) {
  //       // 如果我们在设置跳转的过程中没有设置push 或 back，提示开发者，你要设置
  //       // 保证开发者一定要传递这个routerType，且routerType 或者 back 或者 none
  //       const result = ROUTER_TYPE_ENUM.includes(val);
  //       if (!result) {
  //         // routerType 的值不是push back none 三者之一，提示错误信息
  //         // 抛出异常
  //         throw new Error('你的router_type必须是ROUTER_TYPE_ENUM的其中一个');
  //       }
  //       return result;
  //     }
  //   },
  // 接收显示的组件,也是任务栈中第一个组件
  mainComponentName: {
    type: String,
  }
});

let transitionName = ref('');
const router = useRouter();
// 在路由守卫中设置动画名称
router.beforeEach((to, name) => {

  const toPath = VirtualTaskStack.value.findIndex(ele => ele == to.name);
  const fromPath = VirtualTaskStack.value.findIndex(ele => ele == name.name);
  transitionName.value = toPath < fromPath ? 'back' : 'push';
  // to 是即将跳转的目的路由
  //   transitionName.value = props.routerType;
  // 进栈出栈操作
  if (transitionName.value === ROUTER_TYPE_PUSH) {
    // 进栈的操作
    VirtualTaskStack.value.push(to.name)
  } else if (transitionName.value === ROUTER_TYPE_BACK) {
    // 出栈的操作
    VirtualTaskStack.value.pop()
  }
  if (to.name === props.mainComponentName) {
    // 跳回首页  请客任务栈的操作=>就是把数组重置
    clearTAsk()
  }

  //   console.log(VirtualTaskStack.value)
});

// isAimate 控制动画执行
let isAnimate = ref(false)
const beforEnter = () => {
  isAnimate.value = true
}

const afterLeave = () => {
  isAnimate.value = false

}

// 初始化空的任务栈  先把首页放在初始化数组中
let VirtualTaskStack = ref([props.mainComponentName])


// 定义重置任务栈方法
const clearTAsk = () => {
  VirtualTaskStack.value = [props.mainComponentName]
}
</script>

<style lang="scss" scoped>
.ding {
  position: fixed;
  left: 0;
  top: 0;
  width: 100%;
}

// push页面时：新页面的进入动画
.push-enter-active {
  animation-name: push-in;
  animation-duration: 0.4s;
}
// push页面时：老页面的退出动画
.push-leave-active {
  animation-name: push-out;
  animation-duration: 0.4s;
}
// push页面时：新页面的进入动画
@keyframes push-in {
  0% {
    transform: translate(100%, 0);
  }
  100% {
    transform: translate(0, 0);
  }
}
// push页面时：老页面的退出动画
@keyframes push-out {
  0% {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(-100%, 0);
  }
}

// 后退页面时：即将展示的页面动画
.back-enter-active {
  animation-name: back-in;
  animation-duration: 0.4s;
}
// 后退页面时：后退的页面执行的动画
.back-leave-active {
  animation-name: back-out;
  animation-duration: 0.4s;
}
// 后退页面时：即将展示的页面动画
@keyframes back-in {
  0% {
    width: 100%;
    transform: translate(-100%, 0);
  }
  100% {
    width: 100%;
    transform: translate(0, 0);
  }
}
// 后退页面时：后退的页面执行的动画
@keyframes back-out {
  0% {
    width: 100%;
    transform: translate(0, 0);
  }
  100% {
    width: 100%;
    transform: translate(100%, 0);
  }
}
</style>
